/*
	Copyright (c) 2012 by karmaleaving@qq.com. All rights RESERVED.
*/
/*
	This file defines "class Time" that encapsulate c time functions.
*/
#ifndef __TIME_H_VERSION_KL__
#define __TIME_H_VERSION_KL__

#include "config.h"
#include "math.h"
#include <time.h>
#define _KL_USE_TIMER_
#define _KL_USE_TIMER_FUNCTION_

KL_BEGIN
typedef ::time_t ltime_t;
typedef u4_t stime_t;
typedef ::clock_t clock_t;

class Clock
{
protected:
	clock_t _value;
public:
	typedef u4_t value_type;
	typedef i4_t diff_type;
#ifdef CLOCKS_PER_SECOND
	static const clock_t ClocksPerSecond = CLOCKS_PER_SECOND;
#else
	static const clock_t ClocksPerSecond = 1000;
#endif // CLOCKS_PER_SECOND
	Clock(value_type value = Now())
		: _value(value)
	{
	}
	void set(value_type value = Now())
	{
		_value = value;
	}
	value_type get() const
	{
		return _value;
	}
	static clock_t Now()
	{
		return ::clock();
	}
	value_type second() const
	{
		return _value / ClocksPerSecond;
	}
	value_type ms() const
	{
		return _value / (ClocksPerSecond / 1000);
	}
	diff_type operator - (Clock const &right)
	{
		return _value - right._value;
	}
	diff_type operator - (value_type right)
	{
		return _value - right;
	}
	Clock operator + (diff_type &right)
	{
		return Clock(_value + right);
	}
};

class Time
{
protected:
	mutable ::tm _local;
	ltime_t _value;
public:
	static const int MaxSec  = 60;
	static const int MaxMin  = 60;
	static const int MaxHour  = 24;
	static const int MaxDay  = 31;
	static const int MaxMon = 12;
	static const int MaxWeek = 7;
public:
	static const int January = 0;
	static const int Day1    = 1;
	static const int Sunday  = 0;
	static const ltime_t _TinyBase = 0;
public: // Function.
	Time(ltime_t const value = Now())
		: _value(value)
	{
		set(value);
	}
	void set_date(int year /* = BaseYear */, 
		int month = January /* = 1 */, 
		int day = Day1  /* = 1 */, 
		int hour = 0, 
		int minute = 0, 
		int second = 0,
		bool dst = false)
	{
		_local.tm_isdst = dst;
		_local.tm_year = year;
		_local.tm_mon = month;
		_local.tm_mday = day;
		_local.tm_hour = hour;
		_local.tm_min = minute;
		_local.tm_sec = second;
		_value = ::mktime(&_local);
	}
	void set_tiny(stime_t value)
	{
		set(ToTime(value));
	}
	bool set(ltime_t value)
	{
		_value = value;
		tm * temp = ::localtime(&value);
		if(!temp) return false;
		::memcpy(&_local, temp, sizeof(tm));
		return true;
	}
	ltime_t get() const
	{
		return _value;
	}
	stime_t get_tiny() const
	{
		return ToTiny(_value);
	}
	int year() const
	{
		return _local.tm_year;
	}
	int month() const
	{
		return _local.tm_mon;
	}
	int day() const
	{
		return _local.tm_mday;
	}
	int hour() const
	{
		return _local.tm_hour;
	}
	int minute() const
	{
		return _local.tm_min;
	}
	int second() const
	{
		return _local.tm_sec;
	}
	int week() const
	{
		return _local.tm_wday;
	}
	template<typename String>
	bool str(String &dest)
	{
		return ToStr(dest, _value);
	}
public: 
	// STATIC FUNCTION {
	static ltime_t Now()
	{
		return (ltime_t)::time(0);
	}
	static stime_t ToTiny(ltime_t const &value)
	{
		return (stime_t)(value - _TinyBase);
	}
	static ltime_t ToTime(stime_t const &value)
	{
		return (ltime_t)value + _TinyBase;
	}
	static u4_t CountLeap(u4_t year)
	{
		year += 3;
		return year / 4 - year / 100 + year / 400;
	}
	static bool IsLeap(u4_t year)
	{
		return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
	}
public:	
	template<typename String>
	static bool ToStr(String &dest, time_t value)
	{
		char * temp = ::ctime(&value);
		if(!temp) return false;
		dest.append(temp);
		return true;
	}
	// STATIC FUNCTION }
};
KL_END
#endif // __TIME_H_VERSION_KL__
